package ink.ykb.j2CacheDemo.service;

import java.util.List;
import java.util.concurrent.locks.StampedLock;

import org.beetl.sql.core.SQLManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.aop.framework.AopContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import com.fasterxml.jackson.core.JsonProcessingException;

import ink.ykb.j2CacheDemo.dao.UserDao;
import ink.ykb.j2CacheDemo.entity.Department;
import ink.ykb.j2CacheDemo.entity.User;
import ink.ykb.j2CacheDemo.util.Constant;
import ink.ykb.j2CacheDemo.util.ServiceLock;



@Service
@Transactional
public class UserService {

	private Logger logger = LoggerFactory.getLogger(UserService.class);  
	@Autowired
	private SQLManager sqlManager;
	@Autowired
	private UserDao userDao;
	
	@Autowired
	private DepartService departService;
	
	@Cacheable(cacheNames = "user",key = "#id")
	public User getUser(Integer id) {
		User user = userDao.single(id);
		
		Department department = this.departService.getDepartment(user.getDepartmentId());
		user.set("department", department);
		
		return user;
	}
	
	/**
	 * 方式一：
	 * 锁必须要在事务外面，可以使用aop实现一个注解锁或者使用AopContext.currentProxy
	 * @param user
	 * @return
	 */
	@Transactional(propagation = Propagation.NEVER)
	public User updateUserLock(User user) {
		synchronized (this) {
			UserService  userServiceProxy= (UserService)AopContext.currentProxy();
			userServiceProxy.updateUser(user);
    			return user;
            
		}
	}
	
	/**
	 * 方式二：使用aop
	 * @param user
	 * @return
	 */
	@ServiceLock
	@Transactional(propagation = Propagation.REQUIRED)
	@CacheEvict(cacheNames = {"user"}, key = "#user.id")
	public User updateUser(User user) {
		userDao.updateTemplateById(user);
		return user;
	}
	
	public void addUser(User user) {
		userDao.insert(user);
	}
	
}
